import React from 'react';
import DynamicComponent from '../DynamicComponent';

export type DialogButtonProps = {
    disabled?: boolean;
    className?: string;
    loading?: boolean;
    style?: React.CSSProperties;
    onClick?: React.MouseEventHandler<HTMLButtonElement>;
    onMouseDown?: React.MouseEventHandler<HTMLButtonElement>;
    onMouseEnter?: React.MouseEventHandler<HTMLButtonElement>;
    onMouseLeave?: React.MouseEventHandler<HTMLButtonElement>;
};

export interface DialogBasicProps {
    cancelButtonProps?: DialogButtonProps;
    okButtonProps?: DialogButtonProps;
    bodyStyle?: React.CSSProperties;
    maskStyle?: React.CSSProperties;
    style?: React.CSSProperties;
    title?: React.ReactNode;
    content?: React.ReactNode;
    footer?: React.ReactNode;
    header?: React.ReactNode;
    onCancel?: (e: React.MouseEvent) => void | Promise<any>;
    onOk?: (e: React.MouseEvent) => void | Promise<any>;
}

export interface DialogInstance<T extends DialogBasicProps> {
    confirm: (props: T) => void;
    alert: (props: T) => void;
    info: (props: T) => void;
    success: (props: T) => void;
    error: (props: T) => void;
    warn: (props: T) => void;
};

const importer = () => {
    return new Promise(resolve => {
        loadModule().then(({ Modal }) => {
            resolve({ default: Modal });
        });
    })
};

export type DialogProps<T extends DialogBasicProps> = React.PropsWithChildren<T>;

class Dialog<T extends DialogBasicProps> extends React.Component<DialogProps<T>> {

    static confirm(props: DialogBasicProps) {
        useDialog(dialog => {
            dialog.confirm(props);
        });
    }
    
    static alert(props: DialogBasicProps) {
        useDialog(dialog => {
            dialog.alert(props);
        });
    }

    static info(props: DialogBasicProps) {
        useDialog(dialog => {
            dialog.info(props);
        });
    }

    static success(props: DialogBasicProps) {
        useDialog(dialog => {
            dialog.success(props);
        });
    }

    static error(props: DialogBasicProps) {
        useDialog(dialog => {
            dialog.error(props);
        });
    }

    static warn(props: DialogBasicProps) {
        useDialog(dialog => {
            dialog.warn(props);
        });
    } 

    constructor(props) {
        super(props);
    }

    render() {
        if (window['__DIALOG__']) {
            const ComponentClass = window['__DIALOG__'].Modal;
            return <ComponentClass {...this.props} />;
        }
        return <DynamicComponent importer={importer} componentProps={this.props} />;
    }
}

export default Dialog;

function useDialog<T extends DialogBasicProps>(func: (dialog: DialogInstance<T>) => void) {
    let instance = window['__DIALOG__'] && window['__DIALOG__'].default;
    if (instance) {
        func(instance);
        return;
    }

    loadModule().then(() => {
        useDialog<T>(func);
    });
}

const loadModule = (): Promise<any> => {
    return new Promise((resolve) => {
        window['__DIALOG__IMPORTER']().then((mod) => {
            window['__DIALOG__'] = mod;
            resolve(mod);
        });
    });
};

export const initialize = (importer: () => Promise<any>): void => {
    window['__DIALOG__IMPORTER'] = importer;
};
